build(android): Bump compileSdk and targetSdk to API 37 (Android 17)#5768
build(android): Bump compileSdk and targetSdk to API 37 (Android 17)#5768runningcode wants to merge 17 commits into
Conversation
Bump the default AGP fallback to 9.2.1, refresh the AGP-compat matrix, and add AGP 9 migration opt-outs until we adopt built-in Kotlin and the new DSL. Includes AGP 9 compatibility fixes for replay and compose modules. Co-authored-by: Cursor <cursoragent@cursor.com>
Officially support Android 17 by raising SDK levels, resolving AGP 9.2 lint findings, pinning Robolectric tests that lag compileSdk 37, and updating Sauce device-farm configs. Co-authored-by: Cursor <cursoragent@cursor.com>
Add the PR link Danger requires in CHANGELOG.md and rerun screenshot unit tests when Gradle cache omits the test-snapshots output directory. Co-authored-by: Cursor <cursoragent@cursor.com>
Use :test with --no-configuration-cache when snapshots are missing, and skip the sentry-cli upload with a warning instead of failing the job. Co-authored-by: Cursor <cursoragent@cursor.com>
Rerunning a single Android unit-test task after check is unreliable with configuration cache. Warn and skip the sentry-cli upload instead of failing the Build workflow when the directory is absent. Co-authored-by: Cursor <cursoragent@cursor.com>
Restore build.yml, Sauce configs, AGENTS.md, root build.gradle.kts, and the distribution module build script to main so this PR carries only the core Android 17 API bump. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Set jvmToolchain(8) for the navigation, replay, sqlite, and apache http client modules so the Kotlin compile toolchain is fixed under the Android 17 build, and import JvmTarget/KotlinVersion instead of using fully-qualified references. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add jvmToolchain(8) to the fragment and timber modules and import JvmTarget/KotlinVersion instead of using fully-qualified references, matching the other Android modules. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📲 Install BuildsAndroid
|
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The jvmToolchain(8) pin forced javac onto JDK 8, where Error Prone (compiled for JDK 11) cannot load, breaking :sentry-apache-http-client-5 :compileJava and every Spring Boot sample build. Keep jvmTarget at 1.8 for Java 8 bytecode while letting the compiler run on the daemon JDK. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| b193867 | 319.59 ms | 403.09 ms | 83.50 ms |
| 2124a46 | 319.19 ms | 415.04 ms | 95.85 ms |
| a5ab36f | 316.83 ms | 394.54 ms | 77.71 ms |
| dba088c | 320.59 ms | 361.29 ms | 40.70 ms |
| 4e3e79d | 328.10 ms | 395.64 ms | 67.54 ms |
| abfcc92 | 309.54 ms | 380.32 ms | 70.78 ms |
| 539ca63 | 313.51 ms | 355.43 ms | 41.92 ms |
| 3d205d0 | 352.15 ms | 432.53 ms | 80.38 ms |
| bb0ff41 | 312.86 ms | 363.78 ms | 50.92 ms |
| 2195398 | 319.02 ms | 342.38 ms | 23.36 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| b193867 | 1.58 MiB | 2.19 MiB | 620.00 KiB |
| 2124a46 | 1.58 MiB | 2.12 MiB | 551.51 KiB |
| a5ab36f | 1.58 MiB | 2.12 MiB | 555.26 KiB |
| dba088c | 1.58 MiB | 2.13 MiB | 558.99 KiB |
| 4e3e79d | 0 B | 0 B | 0 B |
| abfcc92 | 1.58 MiB | 2.13 MiB | 557.31 KiB |
| 539ca63 | 1.58 MiB | 2.12 MiB | 551.41 KiB |
| 3d205d0 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
| bb0ff41 | 0 B | 0 B | 0 B |
| 2195398 | 0 B | 0 B | 0 B |
AGP 9 only generates unit-test tasks for the configured testBuildType (default "debug"), whereas AGP 8 generated them for every build type. CI disables the debug variant so it only builds and consumes release, which under AGP 9 meant no unit tests were generated or run for the Android library modules at all. Set testBuildType = "release" on the modules that disable the debug variant and have unit tests, so testReleaseUnitTest is generated again. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 36ad602. Configure here.
| } | ||
|
|
||
| sourceSets["main"].apply { manifest.srcFile("src/androidMain/AndroidManifest.xml") } | ||
|
|
There was a problem hiding this comment.
Compose module missing testBuildType
Medium Severity
This PR sets testBuildType = "release" on other Android libraries for AGP 9, but sentry-compose still uses the default debug test build type while CI disables the debug variant. AGP 9 only wires unit tests to testBuildType, so androidUnitTest may not run under ./gradlew check on CI.
Reviewed by Cursor Bugbot for commit 36ad602. Configure here.
Some Android Gradle plugins are published only to Google's Maven repository, which was not available to pluginManagement resolution. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
AGP 9 changed the default source/targetCompatibility for Android modules
from Java 8 to Java 11. The branch pinned Java 8 inconsistently: some
modules had no pin (compiled to Java 11), and others used a java{} block
nested inside android{}, which is not the AGP DSL and had no effect. The
resulting mixed compile-level graph crashed javac with "AssertionError:
unrecognized Attribute name MODULE" on compileReleaseJavaWithJavac.
Pin every published Android library module back to Java 8 via a single
com.android.library block in the root build (mirroring the existing
java-library pin), and drop the now-redundant per-module java{} blocks
and jvmToolchain(8) calls. The Kotlin jvmTarget stays at 8 per module.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
| } | ||
|
|
||
| @SuppressWarnings("deprecation") | ||
| @SuppressLint({"NewApi", "PrivateApi"}) | ||
| @SuppressLint({"NewApi", "PrivateApi", "DiscouragedPrivateApi"}) | ||
| public SentryFrameMetricsCollector( | ||
| final @NotNull Context context, | ||
| final @NotNull ILogger logger, |
There was a problem hiding this comment.
Bug: The try-catch block for reflection on Choreographer does not handle SecurityException, which will cause a crash on Android 17+ during SDK initialization.
Severity: CRITICAL
Suggested Fix
Expand the try-catch block to also catch SecurityException and any other potential exceptions thrown by setAccessible(true). This will prevent the uncaught exception from crashing the application during initialization on newer Android versions.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
sentry-android-core/src/main/java/io/sentry/android/core/internal/util/SentryFrameMetricsCollector.java#L91-L97
Potential issue: During Sentry SDK initialization, the code attempts to use reflection
to access the private field `Choreographer.mLastFrameTimeNanos`. When the application
targets Android 17 (API 37) or higher, this operation will throw a `SecurityException`.
The current implementation only catches `NoSuchFieldException`, meaning the
`SecurityException` will be uncaught, leading to an application crash on startup for
users on Android 17+ devices.
Did we get this right? 👍 / 👎 to inform future reviews.
| } | ||
|
|
||
| @SuppressWarnings("deprecation") | ||
| @SuppressLint({"NewApi", "PrivateApi"}) | ||
| @SuppressLint({"NewApi", "PrivateApi", "DiscouragedPrivateApi"}) | ||
| public SentryFrameMetricsCollector( | ||
| final @NotNull Context context, | ||
| final @NotNull ILogger logger, |
There was a problem hiding this comment.
Bug: The try-catch block for accessing the private Choreographer.mLastFrameTimeNanos field does not handle SecurityException or InaccessibleObjectException, which can be thrown on Android 17 (API 37).
Severity: CRITICAL
Suggested Fix
Expand the catch block to also handle SecurityException and InaccessibleObjectException, or catch a more general Exception, to prevent the SDK initialization from crashing the application on newer Android versions.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
sentry-android-core/src/main/java/io/sentry/android/core/internal/util/SentryFrameMetricsCollector.java#L91-L97
Potential issue: The try-catch block for the reflection call to access
`Choreographer.mLastFrameTimeNanos` only handles `NoSuchFieldException`. When an
application targets Android 17 (API 37), the call to `setAccessible(true)` can throw
`SecurityException` or `InaccessibleObjectException` due to stricter hidden API
enforcement. These exceptions are not caught. Because this code is executed during SDK
initialization, an unhandled exception will cause the application to crash on startup
for users on Android 17 devices.
| } | ||
|
|
||
| @SuppressWarnings("deprecation") | ||
| @SuppressLint({"NewApi", "PrivateApi"}) | ||
| @SuppressLint({"NewApi", "PrivateApi", "DiscouragedPrivateApi"}) | ||
| public SentryFrameMetricsCollector( | ||
| final @NotNull Context context, | ||
| final @NotNull ILogger logger, |
There was a problem hiding this comment.
Bug: The try-catch block for reflection in SentryFrameMetricsCollector does not handle SecurityException or InaccessibleObjectException, which can crash the SDK on initialization on newer Android versions.
Severity: HIGH
Suggested Fix
Expand the catch block in the SentryFrameMetricsCollector constructor to also handle SecurityException and other potential RuntimeExceptions, such as InaccessibleObjectException. This will prevent an SDK crash if reflection access is denied, allowing the feature to degrade gracefully.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
sentry-android-core/src/main/java/io/sentry/android/core/internal/util/SentryFrameMetricsCollector.java#L91-L97
Potential issue: In the `SentryFrameMetricsCollector` constructor, reflection is used to
access the private field `Choreographer.mLastFrameTimeNanos`. The associated `try-catch`
block only handles `NoSuchFieldException`. On newer Android versions (API 37+), stricter
enforcement against accessing hidden APIs can cause `setAccessible(true)` to throw
`SecurityException` or `InaccessibleObjectException`. Because these exceptions are not
caught, they will propagate out of the constructor, crashing the Sentry SDK during its
initialization process and potentially the entire application.
Raise the minimum AGP to 9.1.1 (default fallback 9.2.1) and perform the AGP 9 migration: refresh the AGP-compat matrix, add the AGP 9 opt-outs (android.builtInKotlin/newDsl, lint 9.2.1), pin Java and Kotlin targets to 8 across the Android library modules, set testBuildType to release for unit tests (including sentry-compose), bump the uitest modules to JVM 11, and resolve the AGP 9.2 lint findings. Robolectric 4.15 caps at API 35, so pin the affected tests with @config(sdk = [35]) to keep them green against targetSdk 36. Split out from the API 37 bump (#5768) so the toolchain upgrade lands on its own. compileSdk/targetSdk stay at 36 here. Co-authored-by: Adam Brown <adam.brown@sentry.io> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
Raise the minimum AGP to 9.1.1 (default fallback 9.2.1) and perform the AGP 9 migration: refresh the AGP-compat matrix, add the AGP 9 opt-outs (android.builtInKotlin/newDsl, lint 9.2.1), pin Java and Kotlin targets to 8 across the Android library modules, set testBuildType to release for unit tests (including sentry-compose), bump the uitest modules to JVM 11, and resolve the AGP 9.2 lint findings. Robolectric 4.15 caps at API 35, so pin the affected tests with @config(sdk = [35]) to keep them green against targetSdk 36. lint 9.2.1 flags compileSdk 36 as outdated (37 is available); disable GradleDependency for the Android modules since the SDK bump lives in the API 37 PR. Split out from the API 37 bump (#5768) so the toolchain upgrade lands on its own. compileSdk/targetSdk stay at 36 here. Co-authored-by: Adam Brown <adam.brown@sentry.io> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
Raise the minimum AGP to 9.0.0 (default fallback 9.2.1) and perform the AGP 9 migration: refresh the AGP-compat matrix (9.0.0/9.1.1/9.2.1), add the AGP 9 opt-outs (android.builtInKotlin/newDsl, lint 9.2.1), pin Java and Kotlin targets to 8 across the Android library modules, set testBuildType to release for unit tests (including sentry-compose), bump the uitest modules to JVM 11, and resolve the AGP 9.2 lint findings. Robolectric 4.15 caps at API 35, so pin the affected tests with @config(sdk = [35]) to keep them green against targetSdk 36. lint 9.2.1 flags compileSdk 36 as outdated (37 is available); disable GradleDependency for the Android modules since the SDK bump lives in the API 37 PR. Split out from the API 37 bump (#5768) so the toolchain upgrade lands on its own. compileSdk/targetSdk stay at 36 here. Co-authored-by: Adam Brown <adam.brown@sentry.io> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
Raise the minimum AGP to 9.0.0 (default fallback 9.2.1) and perform the AGP 9 migration: refresh the AGP-compat matrix (9.0.0/9.1.1/9.2.1), add the AGP 9 opt-outs (android.builtInKotlin/newDsl, lint 9.2.1), pin Java and Kotlin targets to 8 across the Android library modules, set testBuildType to release for unit tests (including sentry-compose), bump the uitest modules to JVM 11, and resolve the AGP 9.2 lint findings. Robolectric 4.15 caps at API 35, so pin the affected tests with @config(sdk = [35]) to keep them green against targetSdk 36. lint 9.2.1 flags compileSdk 36 as outdated (37 is available); disable GradleDependency for the Android modules since the SDK bump lives in the API 37 PR. Split out from the API 37 bump (#5768) so the toolchain upgrade lands on its own. compileSdk/targetSdk stay at 36 here. Co-authored-by: Adam Brown <adam.brown@sentry.io> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U
Raise the minimum AGP to 9.0.0 (default fallback 9.2.1) and perform the AGP 9 migration: refresh the AGP-compat matrix (9.0.0/9.1.1/9.2.1), add the AGP 9 opt-outs (android.builtInKotlin/newDsl, lint 9.2.1), pin Java and Kotlin targets to 8 across the Android library modules, set testBuildType to release for unit tests (including sentry-compose), bump the uitest modules to JVM 11, and resolve the AGP 9.2 lint findings. Robolectric 4.15 caps at API 35, so pin the affected tests with @config(sdk = [35]) to keep them green against targetSdk 36. lint 9.2.1 flags compileSdk 36 as outdated (37 is available); disable GradleDependency for the Android modules since the SDK bump lives in the API 37 PR. Split out from the API 37 bump (#5768) so the toolchain upgrade lands on its own. compileSdk/targetSdk stay at 36 here. Co-authored-by: Adam Brown <adam.brown@sentry.io> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmE8hdaj9H9K61opK2PZ6U


Bumps
compileSdkandtargetSdkto API 37 (Android 17) and raises the minimum AGP to 9.1.1 for the Android 17 toolchain.This is a slimmed-down version of
feat/android-17-api-bump, excluding the CI, tooling, and distribution-module changes (build.yml, Sauce configs,AGENTS.md, rootbuild.gradle.kts, andsentry-android-distribution/build.gradle.kts) so it carries only the core API bump.🤖 Generated with Claude Code